package com.maimao.cart.service;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baidu.fsg.uid.impl.CachedUidGenerator;
import com.google.common.collect.Lists;
import com.maimao.cart.client.CouponClient;
import com.maimao.cart.client.GoodsClient;
import com.maimao.core.constant.Constants;
import com.maimao.core.constant.ListData;
import com.maimao.core.exception.MaiMaoDaoException;
import com.maimao.core.model.resp.Result;
import com.maimao.core.utils.DateUtils;
import com.maimao.mg.repository.ShoppingCartRepository;
import com.maimao.mg.service.MgCouponService;
import com.maimao.model.cart.ShoppingCart;
import com.maimao.model.cart.ShoppingCartVo;

import com.maimao.model.info.Coupon;
import com.maimao.model.info.MgCoupon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class ShoppingCartService {
    @Autowired
    private CachedUidGenerator cachedUidGenerator;

    @Autowired
    private ShoppingCartRepository shoppingCartRepository;

    @Autowired
    private MgCouponService mgCouponService;

    @Autowired
    private GoodsClient goodsClient;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private CouponClient couponClient;

    /**
     * 合并离线数据 将购物车已存在的商品，修改加入时间； 不存在的，批量添加到购物车
     *
     * @param shoppingCartList 购物车数据
     */
    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public void mergeData(List<ShoppingCart> shoppingCartList) {
        if (ObjectUtil.isNotEmpty(shoppingCartList)) {
            Iterator<ShoppingCart> iterator = shoppingCartList.iterator();
            while (iterator.hasNext()) {
                ShoppingCart shoppingCart = iterator.next();
                ShoppingCart target = shoppingCartRepository.findByUserIdAndSkuId(shoppingCart.getUserId(), shoppingCart.getSkuId());
                if (target != null) {
                    Query query = new Query();
                    query.addCriteria(Criteria.where("_id").is(target.getId()));
                    Update update = new Update();
                    update.set("modify_time", DateUtils.now());
                    update.inc("num", shoppingCart.getNum());
                    mongoTemplate.updateFirst(query, update, ShoppingCart.class);
                    iterator.remove();
                }
            }
            if (ObjectUtil.isNotEmpty(shoppingCartList)) {
                shoppingCartList.forEach(shoppingCart -> {
                    shoppingCart.setModifyTime(DateUtils.now());
                    shoppingCart.setTotalPrice(new BigDecimal(shoppingCart.getPrice().longValue() * shoppingCart.getNum()));
                    shoppingCart.setId(cachedUidGenerator.getUID());
                });
                shoppingCartRepository.saveAll(shoppingCartList);
            }
        }
    }

    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public void addCart(ShoppingCart shoppingCart) {
        ShoppingCart target = shoppingCartRepository.findByUserIdAndSkuId(shoppingCart.getUserId(), shoppingCart.getSkuId());
        if (target != null) {
            Query query = new Query();
            query.addCriteria(Criteria.where("_id").is(target.getId()));
            Update update = new Update();
            update.set("modify_time", DateUtils.now());
            update.inc("num", shoppingCart.getNum());
            mongoTemplate.updateFirst(query, update, ShoppingCart.class);
        } else {
            shoppingCart.setModifyTime(DateUtils.now());
            shoppingCart.setTotalPrice(new BigDecimal(shoppingCart.getPrice().longValue() * shoppingCart.getNum()));
            shoppingCart.setId(cachedUidGenerator.getUID());
            shoppingCartRepository.save(shoppingCart);
        }

    }

    public ShoppingCart queryBySkuId(Long skuId, Long userId) {
        ShoppingCart target = shoppingCartRepository.findByUserIdAndSkuId(userId, skuId);
        return target;
    }

    public List<ShoppingCartVo> shoppingCartData(Long userId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("user_id").is(userId));
        List<ShoppingCart> shoppingCarts = mongoTemplate.find(query, ShoppingCart.class);
        if (shoppingCarts != null && shoppingCarts.size() > 0) {
            Map<Long, List<ShoppingCart>> shopGroup = shoppingCarts.stream().collect(Collectors.groupingBy(ShoppingCart::getShopId));
            if (shopGroup != null || shopGroup.size() > 0) {
                List<ShoppingCartVo> shoppingCartVos = Lists.newArrayListWithCapacity(shopGroup.size());
                ShoppingCartVo vo;
                for (Map.Entry<Long, List<ShoppingCart>> entry : shopGroup.entrySet()) {
                    vo = new ShoppingCartVo();
                    vo.setShopId(entry.getKey());
                    vo.setName("店铺：" + entry.getValue().get(0).getShopName());
                    List<ShoppingCart> children = entry.getValue();
                    LocalDateTime latestTime = children.get(0).getModifyTime();
                    for (int i = 1; i < children.size(); i++) {
                        LocalDateTime modifyTime = children.get(i).getModifyTime();
                        if (modifyTime.compareTo(latestTime) > 0) {
                            latestTime = modifyTime;
                        }
                    }
                    vo.setLatestTime(latestTime);
                    vo.setChildren(children);
                    Result<List<MgCoupon>> couponRes = couponClient.queryCouponsByShop(vo.getShopId());
                    if (couponRes != null && couponRes.getData() != null) {
                        vo.setSpecStr(couponRes.getData());
                    }
                    shoppingCartVos.add(vo);
                }
                shoppingCartVos = shoppingCartVos.stream().sorted(Comparator.comparing(ShoppingCartVo::getLatestTime).reversed()).collect(Collectors.toList());

                return shoppingCartVos;
            }
        }
        return ListData.EMPTY_LIST;

    }

    public void updateNum(Long id, Integer num, BigDecimal totalPrice) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));
        Update update = new Update();
        update.set("num", num).set("total_price", totalPrice.setScale(2, RoundingMode.HALF_UP));
        mongoTemplate.updateFirst(query, update, ShoppingCart.class);
    }

    public void deleteCarBatch(List<Long> ids) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").in(ids));
        mongoTemplate.remove(query, ShoppingCart.class);
    }

    public void removeInvalidGoods(Long userId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("user_id").is(userId).and("valid").is(false));
        mongoTemplate.remove(query, ShoppingCart.class);

        List<ShoppingCart> shoppingCarts = mongoTemplate.find(new Query().addCriteria(Criteria.where("user_id").is(userId)), ShoppingCart.class);
        if (ObjectUtil.isNotEmpty(shoppingCarts)) {
            Set<Long> skuIds = shoppingCarts.stream().map(ShoppingCart::getSkuId).collect(Collectors.toSet());
            //清除已下架或无库存的商品
            Result<List<Long>> checkSku = goodsClient.checkSkuBatchWithRes(Lists.newArrayList(skuIds));
            if (checkSku != null && ObjectUtil.isNotEmpty(checkSku.getData())) {
                List<Long> invalidSkuIds = checkSku.getData();
                mongoTemplate.remove(new Query().addCriteria(Criteria.where("user_id").is(userId).and("sku_id").in(invalidSkuIds)),ShoppingCart.class);
            }

        }
    }


}
